package com.bsj.power.pls.config.net.netty;

import com.bsj.power.pls.config.net.netty.common.Decoder;
import com.bsj.power.pls.config.net.netty.common.HandleUWB;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.net.InetAddress;
import java.net.InetSocketAddress;

/**
 * @author yinhao
 * @version 1.0
 * @description netty tcp服务端
 * @date 2024/9/23
 */
@Slf4j
public class TcpSerUntil {
    private final int CONST_THREAD_BOSS = 4;
    private final int CONST_THREAD_WORKER = 8;
    private ServerBootstrap bootstrap = null;
    private EventLoopGroup boss_group = null;
    private EventLoopGroup worker_group = null;

    public TcpSerUntil(){}

    public boolean init(int port, Object o) {
        this.bootstrap = new ServerBootstrap();
        if (System.getProperty("os.name").toLowerCase().contains("linux")) {
            this.boss_group = new EpollEventLoopGroup(4);
            this.worker_group = new EpollEventLoopGroup(8);
        } else {
            this.boss_group = new NioEventLoopGroup(4);
            this.worker_group = new NioEventLoopGroup(8);
        }
        this.bootstrap.group(this.boss_group, this.worker_group);
        this.bootstrap.channel(NioServerSocketChannel.class);
        this.bootstrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        this.bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(new Decoder((AnalysisData) o), new HandleUWB((AnalysisData) o));
            }
        });
        this.bootstrap.option(ChannelOption.SO_BACKLOG, 500);
        InetAddress inet_addr = null;

        try {
            inet_addr = InetAddress.getByName("0.0.0.0");
            InetSocketAddress sock_addr = new InetSocketAddress(inet_addr, port);
            this.bootstrap.bind(sock_addr).sync();
            return true;
        } catch (Exception var5) {
            if (var5 instanceof InterruptedException) {
                log.info("net bind err:" + port);
            } else {
                log.info("ip err:" + inet_addr);
            }

            this.boss_group.shutdownGracefully();
            this.worker_group.shutdownGracefully();
            this.boss_group = null;
            this.worker_group = null;
            this.bootstrap = null;
            return false;
        }
    }

    public void stop() {
        this.boss_group.shutdownGracefully();
        this.worker_group.shutdownGracefully();
        this.boss_group = null;
        this.worker_group = null;
        this.bootstrap = null;
    }

    public static void send(ChannelHandlerContext ctx, byte[] data) {
        final ByteBuf buf = PooledByteBufAllocator.DEFAULT.heapBuffer(data.length);
        buf.writeBytes(data);
        final Channel channel = ctx.channel();
        if (channel.eventLoop().inEventLoop()) {
            channel.writeAndFlush(buf);
        } else {
            channel.eventLoop().execute(new Runnable() {
                @Override
                public void run() {
                    channel.writeAndFlush(buf);
                }
            });
        }

    }

    public boolean initWebSocket(int port, Object o) {
        this.bootstrap = new ServerBootstrap();
        this.boss_group = new NioEventLoopGroup();
        this.worker_group = new NioEventLoopGroup();
        this.bootstrap.group(this.boss_group, this.worker_group)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast((ChannelInitializer) o);

                    }
                })
                .option(ChannelOption.SO_BACKLOG, 1024);
        InetAddress inet_addr = null;

        try {
            inet_addr = InetAddress.getByName("0.0.0.0");
            InetSocketAddress sock_addr = new InetSocketAddress(inet_addr, port);
            this.bootstrap.bind(sock_addr).sync();
            return true;
        } catch (Exception var5) {
            if (var5 instanceof InterruptedException) {
                log.info("net bind err:" + port);
            } else {
                log.info("ip err:" + inet_addr);
            }

            this.boss_group.shutdownGracefully();
            this.worker_group.shutdownGracefully();
            this.boss_group = null;
            this.worker_group = null;
            this.bootstrap = null;
            return false;
        }
    }
}
